// 基本示例

import { visitFunctionBody } from "typescript";

/**
 * 类的基本定义与使用
 */

class Person {
  userName: string
  constructor(userName: string) {
    this.userName = userName
  }
  say(msg: string): string {
    console.log(`[Person] ${this.userName}:${msg}.`);
    return `${this.userName}:${msg}.`
  }
}

const Jhon = new Person('Jhon')
Jhon.say('hello world')

// 类的继承

class Men extends Person {

  constructor(userName: string) {
    super(userName)
  }

  run(distance: number = 0): string {
    console.log(`[Men] ${this.userName} run ${distance}m.`)
    return `[Men] ${this.userName} run ${distance}m.`
  }

  say(): string {
    console.log(`[Men] ${this.userName} say hello.`)
    return `[Men] ${this.userName} say hello.`
  }

}

let Bob = new Men('Bob')
Bob.say()
Bob.run(11)

// 公共、私有与受保护的修饰符
// 默认 public | 什么都不写就是 public 模式
// 私有 private | 当成员被标记成 private 时，它就不能在声明它的类的外部访问
// 受保护 protected | 与 private 修饰符行为很相似，但有一点不通，protected 成员在派生类中仍然可以访问

// 动物性别
enum aniSex { Girl = 0, Boy }

// 动物信息
interface aniInfo {
  name: string
  age: number
  sex: aniSex
}

// 声明一个动物 类 
class Animal {

  public name: string = 'Dog'

  public constructor(name: string) {
    this.name = name
  }

  public run(distance: number = 10) {
    console.log(`[Animal] ${this.name} run ${distance}M.`)
  }

}

class Dog extends Animal {

  private age: number = 3
  protected sex: number = 0

  public constructor(aniInfo: aniInfo) {
    super(aniInfo.name)
    this.age = aniInfo.age
    this.sex = aniInfo.sex
  }

  public say() {
    console.log(`[Dog] ${this.name} age is ${this.age} say wolf~ wolf~ wolf~`)
  }
}

class snowDog extends Dog {

  constructor(aniInfo: aniInfo) {
    super(aniInfo)
  }

  read() {
    // console.log(`[snowDog] sex is ${aniSex[this.sex]} age is ${this.age}.`); // age 读不到  sex 能读到
    console.log(`[snowDog] sex is ${aniSex[this.sex]}`);
  }

}

let Haski = new snowDog({ name: 'Hasiki', age: 3, sex: 1 })
Haski.run()
Haski.say()
Haski.read()

console.log('[Haski.name] - ', Haski.name);
// console.log(Haski.age); // 外部是访问不到的
// console.log(Haski.sex); // 外部是访问不到的

// readonly 修饰符
class P {
  readonly name: string = 'sssssss'
  constructor(name: string) {
    this.name = name
  }
}
let JJ = new P('Snake')
// JJ.name = 'xiuxiu'

// 存取器
class Student {
  firstName: string = 'A'
  lastName: string = 'B'

  get fullName(): string {
    return this.firstName + '_' + this.lastName
  }

  set fullName(val) {
    const names = val.split('_')
    this.firstName = names[0]
    this.lastName = names[1]
  }
}

const pupil = new Student()
console.log(pupil.fullName)

pupil.firstName = 'Jhon'
pupil.lastName = 'Ramber'
console.log(pupil.fullName)

pupil.fullName = '诸葛_孔明'
console.log(pupil.firstName, pupil.lastName)

// 静态属性
class selfArray {
  static toString(arr: Array<number>): string {
    return arr.join('_')
  }
}

console.log(selfArray.toString([1, 2, 3, 4, 5, 6, 7]));

// 抽象类 
// 什么叫做抽象类？就是一个只能用(继承)但是无法被实例化的类
abstract class House {

}



